﻿using Android.App;
using Android.Content;
using Android.Hardware;
using Android.Media.Audiofx;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using nhCore.Modbus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static Android.Graphics.Paint;

namespace nhCore
{
    /// <summary>
    /// 仪表或传感器的基类，单独设备地址，包含一个或多个气象要素，对应Sensors表及关联Configs
    /// </summary>
    public abstract class BaseDevice
    {
        #region Sensors表对应，关联Configs表
        /// <summary>
        /// 设备地址
        /// </summary>
        public byte Address { get; set; }

        /// <summary>
        /// 设备名称，如：自动气象站
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 气象要素配置列表
        /// </summary>
        public List<ElementConfig> Configs { get; set; } = new List<ElementConfig>();
        #endregion

        /// <summary>
        /// 显示站点名称及[设备地址]
        /// </summary>
        public string Display
        {
            get { return string.Format($"{Name}[{Address.ToString().PadLeft(2, '0')}]"); }
        }


        #region 用于组成命令
        /// <summary>
        /// 使用的最大寄存器，用于生产命令
        /// </summary>
        private ushort MaxReg;

        internal ushort MinReg { get; private set; }

        /// <summary>
        /// 控制码
        /// </summary>
        internal byte ControlCode { get; private set; }

        /// <summary>
        /// 连续寄存器数量
        /// </summary>
        internal byte RegCounts { get => (byte)(MaxReg - MinReg + 1); }

        /// <summary>
        /// 气象数据解码器列表
        /// </summary>
        internal List<Modbus.Decoder> Decoders { get; set; } = new List<Modbus.Decoder>();
        #endregion

        /// <summary>
        /// 根据Config生成命令帧、解码器
        /// </summary>
        /// <param name="controlCode"></param>
        internal void InitializeCmdHelp(byte controlCode)
        {
            ControlCode = controlCode;
            UInt16 maxReg = (ushort)Configs.Max(c => c.Index);

            ElementConfig config = Configs.Where(c => c.Index == maxReg).First() as ElementConfig;

            if (config.DataType == typeof(Int32) || config.DataType == typeof(float))
            {
                maxReg++;//最后一个寄存器为4字节，则要加1
            }
            MaxReg = maxReg;
            MinReg = (ushort)Configs.Min(c => c.Index);

            AuotAddDecoder();
        }

        /// <summary>
        /// 自动根据Configs加解码器
        /// </summary>
        internal virtual void AuotAddDecoder()
        {
            Modbus.Decoder decoder;
            foreach (var c in Configs)
            {
                int decIndex = Decoders.FindIndex((con) => con.Config.Index == c.Index);
                if (decIndex == -1)//没有对应解码器
                {
                    if (c.DataType == typeof(Int32))
                    {
                        decoder = new nhCore.Modbus.Int32Decoder();
                    }
                    else if (c.DataType == typeof(float))
                    {
                        decoder = new nhCore.Modbus.FloatDecoder();
                    }
                    else
                    {
                        decoder = new nhCore.Modbus.WeatherDecoder();
                    }
                    decoder.Config = c;

                    Decoders.Add(decoder); //加气象解码器到列表
                }
                else //已有解码器不再加入
                {
                    decoder = Decoders[decIndex];
                }
                decoder.ReturnDataIndex = (UInt16)(c.Index - MinReg);
            }
        }

        public void AdddDecoder(Modbus.Decoder decoder)
        {
            Decoders.Add(decoder);
        }

        /// <summary>
        /// 取命令列表，新建命令列表，新建命令，气象命令附加解码器，时间和配置命令无解码器
        /// </summary>
        /// <returns></returns>
        public virtual List<CmdFrame> GetSentCmds(byte code = 0x04, int workDelayTime = 1000, int sleepDelayTime = 1000)
        {

            List<CmdFrame> ls = null;

            if (Configs.Count > 0)
            {
                InitializeCmdHelp(code);
                ls = new List<CmdFrame>();
                //实时命令
                RealTimeCmd rtc = new RealTimeCmd(Address, ControlCode, workDelayTime, sleepDelayTime)
                {
                    Index = MinReg,
                    Len = RegCounts
                };
                (rtc.Analyzer as WeatherAnalyzer).Decoders = Decoders;
                ls.Add(rtc);
            }

            return ls;
        }
    }
}